local i

local function print(text)
	DEFAULT_CHAT_FRAME:AddMessage("|c0033CCFF"..text);
end



function OZ_EmptyFunction(n)
	return 0;
end

-------------------------------------------------------------------------
--   INPUT FUNCTIONS
--
--   These functions initialise the bar arrays with the initial data
--
-------------------------------------------------------------------------
function OZ_InputAddMembers(n)
	-- Go through the raid roster and add all members to thistables bars...
	local i,p
	p = OZ_Input.nBars
	local class = OZ_Config[n].filter.class
	local group = OZ_Config[n].filter.group
	if( OZ_RaidRoster.nMembers>0 ) then
		for i = 1,OZ_RaidRoster.nMembers do
			-- Filter for class & group
			local member = OZ_RaidRoster.member[i]
			if class[member.fileName] and ((not member.petClass) or class[member.petClass]) then
				local addMe = nil
				if member.subgroup==OZ_PlayerParty then
					-- Player is in MY group, so add if my group is checked
					if group[9] or (not group[10] and group[member.subgroup]) then
						addMe = 1
					end
				elseif group[member.subgroup]==1 then
						addMe = 1
				end

				if addMe then
					p = p+1
					local dest = OZ_Input.bar[p]
					dest.roster = i
					dest.target = 0
					dest.sortWeight = 0
				end
			end
		end
	end
	OZ_Input.nBars = p
end

function GetMainTankList()
	if CT_RA_MainTanks then
		return CT_RA_MainTanks
    elseif oRA and oRA.maintanktable then
        return oRA.maintanktable
	end
end
function OzSetMainTank(num, unit)
	if CT_RA_MainTanks then
		CT_RA_MainTanks[num] = UnitName(unit)
    elseif oRA.modules.LeaderMT then
        return oRA.modules.LeaderMT:Set(num,unit)
	end
end
function OzIsMainTank(unit)
    local n = UnitName(unit);
    if CT_RA_MainTanks then
        for i=1,10 do
            if CT_RA_MainTanks[i] == n then
                return i;
            end
        end
    elseif oRA.maintanktable then
        for i=1,10 do
            if oRA.maintanktable[i] == n then
                return i;
            end
        end
    end
end



function OZ_InputAddCTMainTanks(n)
	-- Go through the raid roster and add all members to this tables bars...
	local i,j,p,max
	p = 0
	max = 0
	
	OzRaid_UpdateUnitData()
	local tankList = GetMainTankList()

	if tankList then
		for i = 1,10 do
			local ctmt = tankList[i]
			local found = nil
			if ctmt then
				j =	OZ_RaidNames[ctmt]
				local mt = OZ_RaidRoster.member[j]
				if mt and mt.name == ctmt then
					p = p+1
					max = p
					local dest = OZ_Input.bar[p]
					dest.roster = j
					dest.target = 0
					dest.sortWeight = p
					dest.unit	= mt.unit
					dest.class	= mt.fileName
					dest.max	= mt.maxHealth
					dest.current= mt.health
					found = true
				end
			end
			if not found then
				p = p+1
				local dest = OZ_Input.bar[p]
				dest.roster = 0
				dest.target = 0
				dest.sortWeight = p
				dest.unit	= nil
				dest.class	= "<none>"
				dest.max	= 1
				dest.current= 0
			end
		end
	end
	OZ_Input.nBars = max
end

function OZ_InputAddCTMainTankTarget(n)
	local i,j,k,p,max
	p = 0
	max = 0

	OzRaid_UpdateTargetData()
	local tankList = GetMainTankList()

	if tankList then
		for i = 1,10 do
			p = p+1
			local ctmt = tankList[i]
			local found = nil
			local dest = OZ_Input.bar[p]
			dest.unit	= nil
			if ctmt then
				j =	OZ_RaidNames[ctmt]
				local mt = OZ_RaidRoster.member[j]
				if mt and mt.name == ctmt then
					dest.unit	= mt.target
					max = p
					if UnitExists(mt.target) then
						for k=1,OZ_RaidRoster.nTargets do
							local t = OZ_RaidRoster.target[k]
							if UnitIsUnit(mt.target, t.unit) then
								-- Found the target!
								dest.roster = 0
								dest.target = k
								dest.sortWeight = p
								dest.class	= t.fileName
								dest.max	= t.maxHealth
								dest.current= t.health
								found = true
								break
							end
						end
					end
				end
			end

			if not found then
				dest.roster = 0
				dest.target = 0
				dest.sortWeight = p
				dest.class	= "<none>"
				dest.max	= 1
				dest.current= 0
			end
		end
	end
	OZ_Input.nBars = max
end

function OZ_InputAddCTMainTankTargetsTarget(n)
	local i,j,k,p,max
	p = 0
	max = 0

	OzRaid_UpdateUnitData()
	OzRaid_UpdateTargetData()
	local tankList = GetMainTankList()
    local member = OZ_RaidRoster.member
    local target = OZ_RaidRoster.target

	if tankList then
		for i = 1,10 do
			p = p+1
			local ctmt = tankList[i]
			local found = nil
			local dest = OZ_Input.bar[p]
			dest.unit	= nil
			if ctmt then
				j =	OZ_RaidNames[ctmt]
--print("i = "..ctmt.."("..j..")")
				local mt = member[j]
				if mt and mt.name == ctmt then
					dest.unit	= mt.target.."target"
--print(" > unit = "..dest.unit)
					max = p
					if UnitExists(mt.target) then
						for k=1,OZ_RaidRoster.nTargets do
							local t = target[k]
							if UnitIsUnit(mt.target, t.unit) then
								-- Found the target!
								if t.targetMember then
									-- This mob has a target!
									local src = member[t.targetMember]
									dest.roster = t.targetMember
									dest.target = 0
									dest.sortWeight = p
									dest.class	= src.fileName
									dest.max	= src.maxHealth
									dest.current= src.health
									found = true
									break
								end
							end
						end
					end
				end
			end

			if not found then
				dest.roster = 0
				dest.target = 0
				dest.sortWeight = p
				dest.class	= "<none>"
				dest.max	= 1
				dest.current= 0
			end
		end
	end
	OZ_Input.nBars = max
end

function OZ_InputAddPartyMembers(n)
	-- Go through the raid roster and add all members to thistables bars...
	local i,p
	p = OZ_Input.nBars
	local class = OZ_Config[n].filter.class
	if( OZ_RaidRoster.nMembers>0 ) then
		for i = 1,OZ_RaidRoster.nMembers do
			-- Filter for class & group
			local member = OZ_RaidRoster.member[i]
			if( member.subgroup == OZ_PlayerParty)then
				if( class[member.fileName] == 1) then
					p = p+1
					local dest = OZ_Input.bar[p]
					dest.roster = i
					dest.target = 0
					dest.sortWeight = 0
				end
			end
		end
	end
	OZ_Input.nBars = p
end

function OZ_InputAddTargets(n)
	-- Go through the raid roster and add all members to thistables bars...
	local i,p
	if( OZ_RaidRoster.nTargets>0 ) then
		for i = 1,OZ_RaidRoster.nTargets do
			p = OZ_Input.nBars + i
			local dest = OZ_Input.bar[p]
			dest.roster = 0
			dest.target = i
			dest.sortWeight = 0
		end
	end
	OZ_Input.nBars = OZ_Input.nBars + OZ_RaidRoster.nTargets
end

function OZ_InputAddHealth()
	local i
	local rt = OZ_RaidRoster.target
	local rm = OZ_RaidRoster.member
	if( OZ_Input.nBars>0 ) then
		for i=1,OZ_Input.nBars do
			local bar = OZ_Input.bar[i]
			local p
			if(bar.roster > 0)then
				p = rm[bar.roster]
			else
				p = rt[bar.target]
			end
			if(p)then
				bar.unit	= p.unit
				bar.class	= p.fileName
				bar.max		= p.maxHealth
				bar.current	= p.health
			else
				bar.unit	= nil
				bar.class	= "TARGET"
				bar.max		= 100
				bar.current	= 0
			end
		end
	end
end

function OZ_InputAddHealthCOMBAT(bars)
	OzRaid_UpdateUnitData()
	local i
	local rt = OZ_RaidRoster.target
	local rm = OZ_RaidRoster.member
	if( bars.nBars>0 ) then
		for i=1,bars.nBars do
			local bar = bars.bar[i]
			local p
			if(bar.roster > 0)then
				p = rm[bar.roster]
			else
				p = rt[bar.target]
			end
			if(p)then
				bar.max		= p.maxHealth
				bar.current	= p.health
				if( bar.max > 0)then
					bar.value	= bar.current / bar.max
				else
					bar.value	= 0
				end
				if( bar.value > 1 )then
					bar.value = 1
				elseif( bar.value < 0 )then
					bar.value = 0
				end
			else
				bar.max		= 100
				bar.current	= 0
			end
		end
	end
end

function OZ_InputAddMTTHealthCOMBAT(bars)
	OzRaid_UpdateUnitData()
	OzRaid_UpdateTargetData()
	local i
	local rt = OZ_RaidRoster.target
	local rm = OZ_RaidRoster.member
	if( bars.nBars>0 ) then
		for i=1,bars.nBars do
			local bar = bars.bar[i]
			local j
			local p = nil
			if UnitExists(bar.unit) then
				j = OZ_RaidNames[ UnitName(bar.unit) ]
				if rm[j] and UnitIsUnit(bar.unit, rm[j].unit) then
					p = rm[j]
					if bar.roster~=j then
						bar.target = 0
						bar.roster = j
						bar.class = p.class
					end
				else
					for j=1,OZ_RaidRoster.nTargets do
						if rt[j] and UnitIsUnit(bar.unit, rt[j].unit) then
							p = rt[j]
							if bar.target~=j then
								bar.roster = 0
								bar.target = j
								bar.class = p.class
							end
							break
						end
					end
					if not p then
						-- Eep -= cant find, just fudge it!
						bar.roster = 0
						bar.target = 0
						bar.class = UnitName(bar.unit)
						bar.max = UnitHealthMax( bar.unit )
						bar.current = UnitHealth( bar.unit )
						if( bar.max > 0)then
							bar.value	= bar.current / bar.max
						else
							bar.value	= 0
						end
					end
				end
			end
			if(p)then
				bar.max		= p.maxHealth
				bar.current	= p.health
				if( bar.max > 0)then
					bar.value	= bar.current / bar.max
				else
					bar.value	= 0
				end
			else
				bar.class	= "<none>"
				bar.max	= 1
				bar.current= 0
				bar.value = 0
			end
			if( bar.value > 1 )then
				bar.value = 1
			elseif( bar.value < 0 )then
				bar.value = 0
			end
		end
	end
end

function OZ_InputAddMana()
	OzRaid_UpdateUnitData()
	local i
	local rt = OZ_RaidRoster.target
	local rm = OZ_RaidRoster.member
	if( OZ_Input.nBars>0 ) then
		for i=1,OZ_Input.nBars do
			local bar = OZ_Input.bar[i]
			local p
			if(bar.roster > 0)then
				p = rm[bar.roster]
			else
				p = rt[bar.target]
			end
			if(p)then
				bar.unit	= p.unit
				bar.class	= p.fileName
				bar.max		= p.maxMana
				bar.current	= p.mana
			else
				bar.unit	= nil
				bar.class	= "TARGET"
				bar.max		= 100
				bar.current	= 0
			end
		end
	end
end

function OZ_InputAddManaCOMBAT(bars)
	local i
	local rt = OZ_RaidRoster.target
	local rm = OZ_RaidRoster.member
	if( bars.nBars>0 ) then
		for i=1,bars.nBars do
			local bar = bars.bar[i]
			local p
			if(bar.roster > 0)then
				p = rm[bar.roster]
			else
				p = rt[bar.target]
			end
			bar.max		= p.maxMana
			bar.current	= p.mana
			if( bar.max > 0)then
				bar.value	= bar.current / bar.max
			else
				bar.value	= 0
			end
			if( bar.value > 1 )then
				bar.value = 1
			elseif( bar.value < 0 )then
				bar.value = 0
			end
		end
	end
end

function OZ_InputRaidMembersHealth(n)
	OzRaid_UpdateUnitData()
	if(not OZ_Config[n].hideGlow)then
		OzRaid_UpdateTargetData()
	end
	OZ_Input.nBars = 0
	OZ_InputAddMembers(n)
	OZ_InputAddHealth()
end

function OZ_InputRaidMembersMana(n)
	OzRaid_UpdateUnitData()
	if(not OZ_Config[n].hideGlow)then
		OzRaid_UpdateTargetData()
	end
	OZ_Input.nBars = 0
	OZ_InputAddMembers(n)
	OZ_InputAddMana()
end

function OZ_InputPartyMembersHealth(n)
	OzRaid_UpdateUnitData()
	if(not OZ_Config[n].hideGlow)then
		OzRaid_UpdateTargetData()
	end
	OZ_Input.nBars = 0
	OZ_InputAddPartyMembers(n)
	OZ_InputAddHealth()
end

function OZ_InputPartyMembersMana(n)
	OzRaid_UpdateUnitData()
	if(not OZ_Config[n].hideGlow)then
		OzRaid_UpdateTargetData()
	end
	OZ_Input.nBars = 0
	OZ_InputAddPartyMembers(n)
	OZ_InputAddMana()
end

function OZ_InputRaidTargetsHealth(n)
	OzRaid_UpdateTargetData()
	OZ_Input.nBars = 0
	OZ_InputAddTargets(n)
	OZ_InputAddHealth()
end

function OZ_InputAllHealth(n)
	OzRaid_UpdateUnitData()
	OzRaid_UpdateTargetData()
	OZ_Input.nBars = 0
	OZ_InputAddMembers(n)
	OZ_InputAddTargets(n)
	OZ_InputAddHealth()
end

OZ_AGG = {
	["TARGET"] = {0,0},
	["DRUID"] = {0,0},
	["HUNTER"] = {0,0},
	["MAGE"] = {0,0},
	["PALADIN"] = {0,0},
	["PRIEST"] = {0,0},
	["ROGUE"] = {0,0},
	["SHAMAN"] = {0,0},
	["WARLOCK"] = {0,0},
	["WARRIOR"] = {0,0},
	["DEATHKNIGHT"] = {0,0},
};

function OZ_InputAggregatedClassHealth(n)
	OZ_Input.nBars = 0
	local class,ac
	local i,key,value
	for key,value in pairs(OZ_AGG) do
		value[0] = 0
		value[1] = 0
	end
	if( OZ_RaidRoster.nMembers>0 ) then
        local rm = OZ_RaidRoster.member
		for i = 1,OZ_RaidRoster.nMembers do
			local member = rm[i]
			class = member.fileName
			if class and OZ_AGG[class] then
                ac = OZ_AGG[class]
				ac[0]	= ac[0] + member.health
				ac[1]	= ac[1] + member.maxHealth
			end
		end
	end
	i = 0
    local filters = OZ_Config[n].filter.class
	for key,value in pairs(OZ_AGG) do
		if( (value[1] > 0) and (filters[key]) ) then
			i = i+1
			local bar = OZ_Input.bar[i]
			bar.roster	= 0
			bar.target	= 0
			bar.current	= value[0]
			bar.max		= value[1]
			bar.class	= key
			bar.unit	= nil
		end
	end
	OZ_Input.nBars = i
end

function OZ_InputAggregatedClassMana(n)
	OZ_Input.nBars = 0
	local class, ac, f
	local i,key,value
	for key,value in pairs(OZ_AGG) do
		value[0] = 0
		value[1] = 0
	end
	if( OZ_RaidRoster.nMembers>0 ) then
		for i = 1,OZ_RaidRoster.nMembers do
			local member = OZ_RaidRoster.member[i]
			class = member.fileName
			if class and OZ_AGG[class] then
                ac = OZ_AGG[class]
				ac[0]	= ac[0] + member.mana
				ac[1]	= ac[1] + member.maxMana
			end
		end
	end
	i = 0
    f = OZ_Config[n].filter.class
	for key,value in pairs(OZ_AGG) do
		if( (value[1] > 0) and (f[key]) ) then
			i = i+1
			local bar = OZ_Input.bar[i]
			bar.roster	= 0
			bar.target	= 0
			bar.current	= value[0]
			bar.max		= value[1]
			bar.class	= key
			bar.unit	= nil
		end
	end
	OZ_Input.nBars = i
end

function OZ_InputDebugRange(n)
	local i, bar
	for i = 1,20 do
        bar = OZ_Input.bar
		bar[i].roster	= 0
		bar[i].target	= 0
		bar[i].current	= 100
		bar[i].max		= 100
		if( CheckInteractDistance("target", i) )then
			bar[i].value	= 1
		else
			bar[i].value	= 0.1
		end
		bar[i].class	= "MAGE"
		bar[i].unit	= target
		bar[i].buffs	= {}
		bar[i].debuff	= nil
	end
	OZ_Input.nBars = 20
end
-------------------------------------------------------------------------
--   FILTER FUNCTIONS
--
--   These functions initialise the bar arrays with the initial data
--
-------------------------------------------------------------------------
function OZ_FilterRemoveBar(n,i)
	-- Simplest way to remove a bar is to copy the last entry 
	-- into position 'i' and reduce the bar count by 1.
	if(i <= OZ_Input.nBars) then
		if(i < OZ_Input.nBars) then

			local currBar = OZ_Input.bar[i]
			OZ_Input.bar[i] = OZ_Input.bar[OZ_Input.nBars]
			OZ_Input.bar[OZ_Input.nBars] = currBar
		end
		OZ_Input.nBars = OZ_Input.nBars - 1
	end
end

function OZ_FilterBars(n)
	local i = 1
	local removed
	local status = OZ_Config[n].filter.status
    local iVal = OZ_Config[n].filter.injuredVal
	while (i <= OZ_Input.nBars) do
		removed = 0
		local statusValid = 1
		local currBar = OZ_Input.bar[i]

		if( currBar.roster > 0 ) then
			local player = OZ_RaidRoster.member[ currBar.roster ]
			-- Player
			if( not status.dead and player.isDead ) then
				removed = 1
			elseif( player.online ) then
				if(not status.online ) then
					removed = 1
				end
			else
				if(not status.offline ) then
					removed = 1
				end
			end
			if( removed == 0)then
				if( player.range ) then
					if( player.range == 2) then
						if( not status.close ) then
							removed = 1
						end
					else
						if( not status.inrange ) then
							removed = 1
						end
					end
				elseif( not status.outofrange ) then
					removed = 1
				end
				if( removed == 0 )then
					if(not player.online or  player.isDead )then
						statusValid = nil
					end
				end
			end
		end
		-- TODO Add mob filtering

		if(removed == 0) then
			if( currBar.max > 0)then
				currBar.value	= currBar.current / currBar.max
			else
				currBar.value	= 0
			end
			if( currBar.value > 1 )then
				currBar.value = 1
			elseif( currBar.value < 0 )then
				currBar.value = 0
			end
			if(statusValid)then
				if( currBar.value < iVal ) then
					if( not status.injured ) then
						removed = 1
					end
				else
					if( not status.healthy) then
						removed = 1
					end
				end
			end
		end
		if( removed == 1)then
			OZ_FilterRemoveBar(n,i)
		else
			i = i+1
		end
	end	
end

-------------------------------------------------------------------------
--   SORT FUNCTIONS
--
--   These functions generate a sorting weight & sort the bars
--		- return '1' if the sort must be directly applied
--		-  anything that has discrete values can be 
-------------------------------------------------------------------------
function OZ_SortByNumberUp(n)
	for i = 1,OZ_Input.nBars do
		OZ_Input.bar[i].sortWeight = -OZ_Input.bar[i].current
	end
end
function OZ_SortByValueDown(n, scale)
	local i
	if(scale)then
		for i = 1,OZ_Input.nBars do
			local bar = OZ_Input.bar[i]
			bar.sortWeight = bar.sortWeight*scale + bar.value
		end
	else
		for i = 1,OZ_Input.nBars do
			local bar = OZ_Input.bar[i]
			bar.sortWeight = bar.value
		end
	end
	return 1
end

function OZ_SortBySubGroup(n, scale)
	local i
    local rm = OZ_RaidRoster.member
	if(scale)then
		for i = 1,OZ_Input.nBars do
			local bar = OZ_Input.bar[i]
			if(bar.roster > 0) then
				bar.sortWeight = bar.sortWeight + rm[bar.roster].subgroup * scale
			end
		end
	else
		for i = 1,OZ_Input.nBars do
			local bar = OZ_Input.bar[i]
			if(bar.roster > 0) then
				bar.sortWeight = rm[bar.roster].subgroup
			end
		end
	end
	return nil
end
local OZ_SORT_CLASS_WEIGHT = {
	["TARGET"] = 0,
	["DRUID"] = 1,
	["HUNTER"] = 2,
	["MAGE"] = 3,
	["PALADIN"] = 4,
	["PRIEST"] = 5,
	["ROGUE"] = 6,
	["SHAMAN"] = 7,
	["WARLOCK"] = 8,
	["WARRIOR"] = 9,
    ["DEATHKNIGHT"] = 10,
};


function OZ_SortByClass(n, scale)
	local i
	if(scale)then
		for i = 1,OZ_Input.nBars do
			local bar = OZ_Input.bar[i]
			local class = bar.class
			if(class) then
				bar.sortWeight = bar.sortWeight + OZ_SORT_CLASS_WEIGHT[class]*scale
			else
				bar.sortWeight = 0
			end
		end
	else
		for i = 1,OZ_Input.nBars do
			local bar = OZ_Input.bar[i]
			local class = bar.class
			if(class) then
				bar.sortWeight = OZ_SORT_CLASS_WEIGHT[class]
			end
		end
	end
	return nil
end

function OZ_SortByIcon(n, scale)
	local i
    local rm = OZ_RaidRoster.member
	for i = 1,OZ_Input.nBars do
		local bar = OZ_Input.bar[i]
		local val
		if(bar.roster > 0) then
			val = rm[bar.roster].iconVal
		elseif(bar.target > 0) then
			val = rm[bar.target].iconVal
		end
		if( not val )then
			val = 9
		end
		if(scale)then
			bar.sortWeight = bar.sortWeight + val*scale
		else
			bar.sortWeight = val
		end
	end
	return nil
end


function OZ_SortByInjured(n, scale)
	local i
	local filter = OZ_Config[n].filter
    local rm = OZ_RaidRoster.member
	if(scale)then
		for i = 1,OZ_Input.nBars do
			local val
			local bar = OZ_Input.bar[i]
			if(bar.roster > 0) then
				if(not rm[bar.roster].online) then
					val = 4
				elseif(rm[bar.roster].isDead) then
					val = 3
				end		
			end
			if(not val)then
				if( bar.value < filter.injuredVal ) then
					val = bar.value
				else
					val = 2
				end
			end
			bar.sortWeight = bar.sortWeight + val*scale
		end
	else
		for i = 1,OZ_Input.nBars do
			local val
			local bar = OZ_Input.bar[i]
			if(bar.roster > 0) then
				if(not rm[bar.roster].online) then
					val = 4
				elseif(rm[bar.roster].isDead) then
					val = 3
				end		
			end
			if(not val)then
				if( bar.value < filter.injuredVal ) then
					val = bar.value
				else
					val = 2
				end
			end
			bar.sortWeight = val
		end
	end
	return 1
end

function OZ_SortByRange(n, scale)
	local i
    local rm = OZ_RaidRoster.member
	if(scale)then
		for i = 1,OZ_Input.nBars do
			local bar = OZ_Input.bar[i]
			local val
			if(bar.roster > 0) then
				if( rm[bar.roster].range )then
					val = 3 - rm[bar.roster].range
				else
					val = 9
				end
			elseif(bar.target > 0) then
				if( rm[bar.target].range )then
					val = 3 - rm[bar.target].range
				else
					val = 9
				end
			else
				val = 1
			end
			bar.sortWeight = bar.sortWeight + val*scale
		end
	else
		for i = 1,OZ_Input.nBars do
			local bar = OZ_Input.bar[i]
			if(bar.roster > 0) then
				if( OZ_RaidRoster.member[bar.roster].range )then
					bar.sortWeight = 3 - rm[bar.roster].range
				else
					bar.sortWeight = 9
				end
			elseif(bar.target > 0) then
				if( OZ_RaidRoster.target[bar.target].range )then
					bar.sortWeight = 3 - rm[bar.target].range
				else
					bar.sortWeight = 9
				end
			else
				bar.sortWeight = 1
			end
		end
	end
	return nil
end

-------------------------------------------------------------------------
--   COLOUR FUNCTIONS
--
--   Functions for setting bar colours
--
-------------------------------------------------------------------------
OZ_CLASS_COLOURS = {
		DRUID	= RAID_CLASS_COLORS["DRUID"],
		HUNTER	= RAID_CLASS_COLORS["HUNTER"],
		MAGE	= RAID_CLASS_COLORS["MAGE"],
		PALADIN	= RAID_CLASS_COLORS["PALADIN"],
		PRIEST	= RAID_CLASS_COLORS["PRIEST"],
		ROGUE	= RAID_CLASS_COLORS["ROGUE"],
		SHAMAN	= RAID_CLASS_COLORS["SHAMAN"],
		WARLOCK	= RAID_CLASS_COLORS["WARLOCK"],
		WARRIOR	= RAID_CLASS_COLORS["WARRIOR"],
		DEATHKNIGHT	= {r=0.77,g=0.12,b=0.23,a=1.0},
		PET		= {r=1.0,g=0.7,b=0.5,a=1.0},

		TARGET	= {r=1.0,g=0.5,b=0.2,a=1.0},

		RANGED	= {r=0.0,g=1.0,b=0.7,a=1.0},
		MELEE	= {r=1.0,g=0.7,b=0.1,a=1.0},
		HEALERS	= {r=1.0,g=0.7,b=0.7,a=1.0},
		TANKS	= {r=1.0,g=0.3,b=0.1,a=1.0},
		["<none>"] = {r=0.5,g=0.5,b=0.5,a=1.0},
	};
    
function OZ_ColourByClass(n)
	-- Set bar colour based on the class
	local i
	for i = 1,OZ_Bars[n].nBars do
		local bar = OZ_Bars[n].bar[i]
		local dest = bar.colour
		local col = OZ_CLASS_COLOURS[bar.class]
		if col then
			dest.r = col.r
			dest.g = col.g
			dest.b = col.b
		else
			dest.r = 0.8
			dest.g = 0.8
			dest.b = 0.8
		end
	end
end

function OZ_ColourHealth(n)
	-- Set bar colour based on the class
	local i
	for i = 1,OZ_Bars[n].nBars do
		local bar = OZ_Bars[n].bar[i]
		local dest = bar.colour
		local val = bar.value
		local a

		if( val == 1.0 ) then
			dest.r=0
			dest.g=0.7
			dest.b=0
		elseif( val > 0.75) then
			a = (1.75 - val)
			dest.r=a
			dest.g=1.0
			dest.b=0
		elseif( val > 0.25) then
			a = (val - 0.25) * 1.4
			dest.r=1
			dest.g=a
			dest.b=0
		else
			dest.r=1
			dest.g=0
			dest.b=0
		end
	end
end

function OZ_ColourMana(n)
	-- Set bar colour based on the class
	local i
	for i = 1,OZ_Bars[n].nBars do
		local bar = OZ_Bars[n].bar[i]
		local dest = bar.colour
		local val = bar.value
		local a
		dest.b=1
		if( val == 1.0 ) then
			dest.r=0.2
			dest.g=0.2
		elseif( val > 0.5) then
			a = (val - 0.5)*2
			dest.r=0.1
			dest.g=1-a
		elseif( val > 0.25) then
			a = (val - 0.25) * 3
			dest.r=1-a
			dest.g=a
		else
			dest.r=0.7
			dest.g=0
		end
	end
end

function OZ_ColourHealthBlueParty(n)
	-- Set bar colour based on the class
	local i
    local rm = OZ_RaidRoster.member

	for i = 1,OZ_Bars[n].nBars do
		local bar = OZ_Bars[n].bar[i]
		local dest = bar.colour
		local val = bar.value
		local a
		if( (bar.roster > 0) and
			(rm[bar.roster].subgroup == OZ_PlayerParty) )then
			dest.b=1
			if( val == 1.0 ) then
				dest.r=0.2
				dest.g=0.2
			elseif( val > 0.5) then
				a = (val - 0.5)*2
				dest.r=0.1
				dest.g=1-a
			elseif( val > 0.25) then
				a = (val - 0.25) * 3
				dest.r=1-a
				dest.g=a
			else
				dest.r=0.7
				dest.g=0
			end
		else		
			dest.b=0
			if( val == 1.0 ) then
				dest.r=0
				dest.g=0.7
			elseif( val > 0.75) then
				a = (1.75 - val)
				dest.r=a
				dest.g=1.0
			elseif( val > 0.25) then
				a = (val - 0.25) * 1.4
				dest.r=1
				dest.g=a
			else
				dest.r=1
				dest.g=0
			end
		end
	end
end
-------------------------------------------------------------------------
--   ICON FUNCTIONS
--
--   Functions to determine what icon to apply to a bar
--
-------------------------------------------------------------------------


-------------------------------------------------------------------------
--   BUFF FUNCTIONS
--
--   Functions to select up to OZ_MAX_BUFFS buffs/debuffs to show on each bar
--
-------------------------------------------------------------------------
if GetAchievementInfo then
    -- WotLK versions
    function OZ_Debuff(unit, index, cure)
        local i,n,r,t,c,d,l,_,m
        if cure then
            if OzPlayerCleanse and UnitIsFriend("player", unit) then
                for i=0,10 do
                    n,r,t,c,_,d,l,m = UnitAura(unit,i,"HARMFUL")
                    if OzPlayerCleanse[_] then
                        return n,r,t,c,d,l,m
                    end
                end
            end
            return;
        else
            n,r,t,c,_,d,l,m = UnitAura(unit,index,"HARMFUL")
        end
        if l then l = l - OZ_CurrentTime end
        return n,r,t,c,d,l,m
    end
    function OZ_Buff(unit, index, cure)
        local n,r,t,c,d,l,_,m,s
        if cure and not UnitIsFriend("player", unit) then
            if OzPlayerCleanse and OzPlayerCleanse["Purge"] then
                n,r,t,c,_,d,l,m,s = UnitAura(unit,index,"HELPFUL CANCELABLE")
                if not n then return end
            end
        else
            n,r,t,c,_,d,l,m = UnitAura(unit,index,"HELPFUL")
        end
        if l then l = l - OZ_CurrentTime end
        return n,r,t,c,d,l,m
    end
else
    function OZ_Debuff(unit, index, cure)
        -- Wrap UnitDebuff so return args are the same as UnitBuff
        local n,r,t,c,_,d,l = UnitDebuff(unit,index,cure)
        return n,r,t,c,d,l
    end
    function OZ_Buff(unit, index, cure)
        return UnitBuff(unit,index,cure)
    end
end
    
function OZ_ShowPlayerBuffs(n)
	local i,j,curr,removed,texture,num,type,key,value,dur,time,mine
	local _, name,debuffs
	i = 1
	local config = OZ_Config[n]
	local status = config.filter.status

	-- test for a curable debuff (the 1 at the end can be a '0' to show all debuffs)
	if(config.allDebuffs) then
		debuffs = 1
	end

	while(i <= OZ_Input.nBars) do
		local buffList,BuffFunc,DebuffFunc
		local bar = OZ_Input.bar[i]
		local buffList = nil
		local debuffList = nil

		if(bar.roster > 0)then
			buffList = config.buffsPlayer
			BuffFunc = OZ_Buff
			DebuffFunc = OZ_Debuff
		elseif(bar.target > 0)then
			buffList = config.buffsMob
			BuffFunc = OZ_Debuff
			DebuffFunc = OZ_Buff
		end

		bar.debuff = nil
		bar.noncure = true
		bar.nBuffs = 0

		curr = 0
		removed = nil

		if bar.unit and BuffFunc then
			name,_,texture, num = DebuffFunc(bar.unit, 1, 1)

			-- Ignore dreamless sleep
			if name and string.find(name,"reamless") then
				name = nil;
				texture = nil;
			end

			if(texture)then
				if(status.curable)then
					bar.debuff = texture
					bar.noncure = false
				else
					removed = 1
				end
			else
				if(not status.notcurable)then
					removed = 1
				else
					-- Check for WATCHED debuffs (power word shield one specifically)
					for j = 1,8 do
						name,_,texture, num, type = DebuffFunc(bar.unit, j)

						if texture then
							if buffList[texture] or debuffs then		
								bar.debuff = texture
								break
							end
						elseif not texture then
							break
						end
					end
				end
			end

			if(not removed)then
				for j = 1,32 do
					name,_,texture, num, dur, time,mine = BuffFunc(bar.unit, j)

					if(texture) then
						local watched = buffList[texture]
						if watched then
							if(status.buffed)then
								-- This buff is a watched buff - yay!
								curr = curr + 1
                                local score = 5-watched[1]
                                if mine then score = score - 10; end
                                
								OZ_SortMap[curr*2 - 1] = score
                                
								OZ_SortMap[curr*2] = texture

								-- BRUTAL HACK ALERT!!!!!
								-- read localised name (for CTRaid buff watching & resolving shared)
								buffList[texture][2] = name
								buffList[texture][3] = dur
								buffList[texture][4] = time
							else
								removed = 1
							end
						end
					else
						break
					end
					if(removed)then
						break
					end
				end
				if( (curr == 0)and(not status.notbuffed) )then
					removed = 1
				end
			end
		end
		if(removed)then
			OZ_FilterRemoveBar(n,i)
		else
			if(curr > 0)then
				-- We found some buffs to show...
				if(curr > 1)then
					OZ_internalMergeSort2(curr * 2)
					if(curr > OZ_MAX_BUFFS)then
						curr = OZ_MAX_BUFFS
					end
				end

				-- Now add them to bars...
				for j = 1,curr do
					local a = OZ_SortMap[j*2]
                    if not bar.buffs[j] then bar.buffs[j] = {}; end
                    local bbuffs = bar.buffs[j];
                    bbuffs[0]	 = a
                    bbuffs[1]	 = buffList[ a ][2]
                    bbuffs[2]	 = buffList[ a ][3]
                    bbuffs[3]	 = buffList[ a ][4]
                    if OZ_SortMap[j*2 - 1] < 0 then bbuffs[4]=1 else bbuffs[4]=nil end
--                    bar.buffs[j]	 = a
--					bar.buffNames[j] = buffList[ a ][2]
--					bar.buffDur[j]	 = buffList[ a ][3]
--					bar.buffTimes[j] = buffList[ a ][4]
				end
			end
			if(curr < OZ_MAX_BUFFS) then
				for j = curr+1,OZ_MAX_BUFFS do
                    if not bar.buffs[j] then bar.buffs[j] = {}; end
                    bar.buffs[j][0] = nil
--					bar.buffs[j] = nil
--					bar.buffNames[j] =nil
				end
			end
			i = i + 1
		end
	end
end


-------------------------------------------------------------------------
--   HEADING FUNCTIONS
--
--   Functions to set bar heading
--
-------------------------------------------------------------------------
function OZ_HeadingHealth(n)
	local state = 1
	local i
	for i = 1,OZ_Bars[n].nBars do
		local bar = OZ_Bars[n].bar[i]
		local val = bar.value
		if( (val<1) and (state == 1) ) then
			bar.header = "Low"
			state = 2
		end
		if( (val==1) and (state < 3) ) then
			bar.header = "Full"
			state = 3
		elseif(State == 2)then
			-- We are amongst the 'injured' list - clear headers
			bar.header = nil
		end			
	end
end

function OZ_HeadingStatus(n)
	local state = 1
	local i
	local injuredVal = OZ_Config[n].filter.injuredVal
	for i = 1,OZ_Bars[n].nBars do
		local bar = OZ_Bars[n].bar[i]
		local val = bar.value

		if( (val<injuredVal) and (state == 1) ) then
			bar.header = "Injured"
			state = 2
		elseif(state < 3)then
			bar.header = nil
		end

		if( (val>injuredVal) and (state < 3) ) then
			if( not bar.header )then
				-- Only tag 'healthy' if there is no other heading
				bar.header = "Healthy"
			end
			state = 3
		end

		local online,dead
		if( bar.roster > 0 ) then
			local member = OZ_RaidRoster.member[ bar.roster ]
			online = member.online
			dead = member.isDead
		elseif( bar.target > 0 ) then
			local target = OZ_RaidRoster.target[ bar.target ]
			online = target.online
			dead = target.isDead
		else
			online = 1
			dead = nil
		end

		if( not online and state<4 )then
			bar.header = "Offline"
			state = 4
		end
		if( not online and state<5 )then
			bar.header = "Dead"
			state = 5
		end
	end
end

function OZ_HeadingGroup(n)
	local i
	local state = -1
    local rm = OZ_RaidRoster.member
    local rt = OZ_RaidRoster.target
	for i = 1,OZ_Bars[n].nBars do
		local bar = OZ_Bars[n].bar[i]
		local val
		if( bar.roster > 0 ) then
			val = rm[ bar.roster ].subgroup
		elseif(  bar.target > 0 ) then
			val = rt[ bar.target ].subgroup
		else
			 val = 0
		end
		if( val ~= state) then
			if(val == 0) then
				bar.header = "Mobs"
			else
				bar.header = "Group "..val
			end
			state = val
		end			
	end
end

function OZ_HeadingClass(n)
	local state = ""
	local i
	for i = 1,OZ_Bars[n].nBars do
		local bar = OZ_Bars[n].bar[i]
		local curr = bar.class
		if( state ~= curr )then
			bar.header = curr
			state = curr
		end
	end
end

function OZ_HeadingRange(n)
	local state = -1
	local i
    local rm = OZ_RaidRoster.member
    local rt = OZ_RaidRoster.target
	for i = 1,OZ_Bars[n].nBars do
		local bar = OZ_Bars[n].bar[i]
		local val
		if( bar.roster > 0 ) then
			val = rm[ bar.roster ].range
		elseif(  bar.target > 0 ) then
			val = rt[ bar.target ].range
		else
			val = nil
		end
		if( val ~= state) then
			if(val)then
				if(val == 2)then
					bar.header = "Close"
				else
					bar.header = "In Range"
				end
			else
				bar.header = "Out of Range"
			end
			state = val
		end			
	end
end

function OZMainTanks()
	local i,k,v;
	local ti=1;
	for i=1,OZ_RaidRoster.nMembers do
		if OZ_RaidRoster.member[i].fileName == "WARRIOR" then
			CT_RA_MainTanks[ti] = OZ_RaidRoster.member[i].name;
			ti=ti+1;
		end
	end
end

-----------------------INPUT-------------------------
	OZ_InputFunctions =	{
							{	["pFunction"]	= OZ_InputRaidMembersHealth,
								["text"]		= "队伍/团队成员生命值",
								["combat"]		= OZ_InputAddHealthCOMBAT,
							},
							{	["pFunction"]	= OZ_InputRaidMembersMana,
								["text"]		= "队伍/团队成员法力值",
								["combat"]		= OZ_InputAddManaCOMBAT,
							},
							{	["pFunction"]	= OZ_InputAggregatedClassHealth,
								["text"]		= "生命值(按职业)",
							},
							{	["pFunction"]	= OZ_InputAggregatedClassMana,
								["text"]		= "法力值(按职业)",
							},
							{	["pFunction"]	= OZ_InputPartyMembersHealth,
								["text"]		= "小队成员生命值",
								["combat"]		= OZ_InputAddHealthCOMBAT,
							},
							{	["pFunction"]	= OZ_InputPartyMembersMana,
								["text"]		= "小队成员法力值",
								["combat"]		= OZ_InputAddManaCOMBAT,
							},

							{	["pFunction"]	= OZ_InputRaidTargetsHealth,
								["text"]		= "目标生命值",
								["always"]		=	1
							},
							{	["pFunction"]	= OZ_InputAddCTMainTanks,
								["text"]		= "CTRaid 主坦克",
								["combat"]		= OZ_InputAddHealthCOMBAT,
							},
							{	["pFunction"]	= OZ_InputAddCTMainTankTarget,
								["text"]		= "CT 主坦目标",
								["combat"]		= OZ_InputAddMTTHealthCOMBAT,
								["always"]		=	1
							},
							{	["pFunction"]	= OZ_InputAddCTMainTankTargetsTarget,
								["text"]		= "CT 主坦目标的目标",
								["combat"]		= OZ_InputAddMTTHealthCOMBAT,
								["always"]		=	1
							},
						};

                        -----------------------SORT-------------------------
	OZ_SortFunctions	= {
							{	["pFunction"]	= OZ_SortByValueDown,
								["text"]		= "状态条长度",
							},
							{	["pFunction"]	= OZ_SortByInjured,
								["text"]		= "生命值状态",
							},
							{	["pFunction"]	= OZ_SortBySubGroup,
								["text"]		= "小队",
							},
							--[[{	["pFunction"]	= OZ_SortByClass,
								["text"]		= "职业",
							},错误报告注解]]
							{	["pFunction"]	= OZ_SortByRange,
								["text"]		= "距离",
							},
							{	["pFunction"]	= OZ_SortByIcon,
								["text"]		= "Raid 标记",
							},
							{	["pFunction"]	= OZ_SortByNumberUp,
								["text"]		= "最大数值优先",
							},
							
						};

	OZ_HeadingFunctions	= {
							{	["pFunction"]	= OZ_HeadingHealth,
								["text"]		= "健康/受伤 标题",
							},
							{	["pFunction"]	= OZ_HeadingStatus,
								["text"]		= "健康/受伤 标题",
							},
							{	["pFunction"]	= OZ_HeadingGroup,
								["text"]		= "小队标题",
							},
							{	["pFunction"]	= OZ_HeadingClass,
								["text"]		= "职业标题",
							},
							{	["pFunction"]	= OZ_HeadingRange,
								["text"]		= "范围标题",
							},
							{	["pFunction"]	= OZ_EmptyFunction,
								["text"]		= "图标",
							},
						};
-----------------------FORMAT-------------------------
	OZ_ColourFunctions ={
							{	["pFunction"]	= OZ_ColourByClass,
								["text"]		= "根据职业着色",
							},
							{	["pFunction"]	= OZ_ColourHealth,
								["text"]		= "健康状况着色-绿>>红",
							},
							{	["pFunction"]	= OZ_ColourMana,
								["text"]		= "法力值状况-蓝>>紫",
							},
							{	["pFunction"]	= OZ_ColourHealthBlueParty,
								["text"]		= "本队蓝色,其他绿色",
							},
						};

